#ifndef EV_SERIAL_PORT_H
#define EV_SERIAL_PORT_H

#include <memory>
#include <QObject>
#include <QSerialPort>
#include <QTimer>
#include <QQueue>
#include <QMutex>
#include "ev_packet.h"

class EvSerial : public QObject
{
    Q_OBJECT

public:
    explicit EvSerial(QObject *parent = nullptr);
    ~EvSerial();
    EvSerial(const EvSerial&) = delete;
    EvSerial& operator=(const EvSerial&) = delete;
    EvSerial(EvSerial&& other) = delete;

    bool open(const QString &portName = "COM7", int baudRate = 115200);
    bool isOpen();
    void close();
    Q_INVOKABLE bool sendPacket(std::shared_ptr<ev_packet_t> packet);

public:
    static std::shared_ptr<ev_packet_t> safeRecvPacket(EvSerial *serial, int timeout_ms = 500);
    static bool safeSendPacket(EvSerial *serial, std::shared_ptr<ev_packet_t> packet);

signals:
    void packetReceived(std::shared_ptr<ev_packet_t> packet);
    void logReceived(std::shared_ptr<ev_packet_t> log);

private slots:
    void onReadyRead();
    void onTimeout();
    void onError(QSerialPort::SerialPortError error);

private:
    QSerialPort *m_serialPort;
    QTimer *m_timeoutTimer;
    ev_parser_t m_parser;
    QMutex m_parserMutex;

    static const int PACKET_TIMEOUT_MS = 100;
    static void ev_parser_callback(const ev_parser_t *parser, const ev_packet_t *packet);
};

#endif // EV_SERIAL_PORT_H
